#include <Windows.h>
#include <mh/win32/timer.hpp>

namespace Mh
{
	TimerWin32::TimerWin32()
		: m_delta_time(-1.0), m_base_time(0), m_paused_time(0), m_stop_time(0), m_prev_time(0), m_current_time(0), m_stopped(false)
	{
		s64 frequency;
		::QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(&frequency));
		m_seconds_per_count = 1.0 / static_cast<f64>(frequency);
	}

	TimerWin32::~TimerWin32()
	{}

	f32 TimerWin32::get_game_time() const
	{
		if (m_stopped)
		{
			return (f32)(((m_stop_time - m_paused_time) - m_base_time) * m_seconds_per_count);
		}
		else
		{
			return (f32)(((m_current_time - m_paused_time) - m_base_time) * m_seconds_per_count);
		}
	}

	f32 TimerWin32::get_delta_time() const
	{
		return static_cast<f32>(m_delta_time);
	}

	void TimerWin32::reset()
	{
		s64 current_time;
		::QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&current_time));
		
		m_base_time = current_time;
		m_prev_time = current_time;
		m_stop_time = 0;
		m_stopped = false;
	}

	void TimerWin32::start()
	{
		s64 start_time;
		::QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&start_time));

		if (m_stopped)
		{
			m_paused_time += (start_time - m_stop_time);	

			m_prev_time = start_time;
			m_stop_time = 0;
			m_stopped  = false;
		}
	}

	void TimerWin32::stop()
	{
		if (!m_stopped)
		{
			s64 current_time;
			::QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&current_time));

			m_stop_time = current_time;
			m_stopped  = true;
		}
	}

	void TimerWin32::tick()
	{
		if (m_stopped)
		{
			m_delta_time = 0.0;
			return;
		}

		s64 current_time;
		::QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&current_time));
		m_current_time = current_time;
		m_delta_time = (m_current_time - m_prev_time) * m_seconds_per_count;
		m_prev_time = m_current_time;

		if (m_delta_time < 0)
		{
			m_delta_time = 0;
		}
	}
}
